package server

import (
	"errors"
	"net/url"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"sieve_admin_server_userpass/pkg/config"
	"sieve_admin_server_userpass/pkg/formatStruct"
	"sieve_admin_server_userpass/pkg/log"
	"sieve_admin_server_userpass/pkg/util/convert"
	"strings"
	"time"
)

var (
	staticallowpathmap = make(map[string]string)
)

func init() {
	initAllowPath()
	config.OnReload(initAllowPath)
}
func initAllowPath() {
	staticallowpathmap["后台"] = *fWebRoot
	config.Sequence("web.allowupload", "允许上传的文件夹", func(cfg *config.SeqCfg) {
		staticallowpathmap[*cfg.String("name", "", "path tip name")] = *cfg.String("path", "", "full path")
	})
}

type mod_staticfile struct{}
type staticfileData struct {
	Id         int
	PathName   string
	FileData   string
	ModId      int
	ModTime    int64
	CreateTime int64
}

func ParsePageLimit(q url.Values) (limit, offset int) {
	page := convert.Atoi(q.Get("page"))
	if page <= 0 {
		page = 1
	}
	limit = convert.Atoi(q.Get("page_size"))
	if limit <= 0 {
		limit = 50
	}
	offset = (page - 1) * limit
	return
}
func (r *mod_staticfile) API_query_search(ctx *Context) interface{} {
	list := make(map[string]any)
	names := []string{}
	for k, _ := range staticallowpathmap {
		names = append(names, k)
	}
	list["PathNames"] = names
	return list
}
func (r *mod_staticfile) API_query_list(ctx *Context) interface{} {
	var totalCnt int
	db.QueryRow("SELECT count(*) from app_static_file").Scan(&totalCnt)
	limit, offset := ParsePageLimit(ctx.Args)

	row, err := db.Query("SELECT "+formatStruct.ParseStructFields(&staticfileData{}).ColsToString()+" from app_static_file ORDER BY ModTime Desc LIMIT ? OFFSET ?", limit, offset)
	if err != nil {
		return err
	}
	defer row.Close()
	list := []*staticfileData{}
	for row.Next() {
		info := &staticfileData{}
		err = row.Scan(formatStruct.ParseStructFields(info).GetPtrs()...)
		if err != nil {
			return err
		}
		list = append(list, info)
	}
	data := make(map[string]interface{})
	data["List"] = list
	data["TotalCnt"] = totalCnt
	return data
}
func (r *mod_staticfile) API_upload_file(ctx *Context) interface{} {
	files, err := UploadFiles(ctx.Http.Request)
	if err != nil {
		return err
	}
	if len(files) == 0 {
		return errors.New("未找到上传文件")
	}
	fileName := files[0]
	if path.Ext(fileName) != ".zip" {
		_ = os.Remove(fileName)
		return errors.New("非zip文件，请重新上传")
	}
	linkPath := *fWebRoot
	if v, ok := staticallowpathmap[ctx.Args.Get("PathName")]; ok {
		linkPath = v
	} else {
		return errors.New("未选择上传pathname")
	}
	fileDir := strings.Replace(fileName, ".zip", "", 1)
	os.MkdirAll(fileDir, os.ModePerm)
	cmd := exec.Command("unzip", fileName)
	cmd.Dir = fileDir
	err = cmd.Run()
	if err == nil {
		os.Remove(fileName)
		os.RemoveAll(linkPath)
		err = os.Symlink(fileDir, linkPath)
		if err != nil {
			log.Err(err)
		}
		sql, vals := formatStruct.ParseStructFields(&staticfileData{
			PathName:   ctx.Args.Get("PathName"),
			FileData:   strings.Replace(fileDir, staticFile, "", 1),
			ModTime:    time.Now().Unix(),
			ModId:      ctx.Uid,
			CreateTime: time.Now().Unix(),
		}, "Id").FormatAddSqlNoArgs("app_static_file")
		_, err = db.Exec(sql, vals...)
	}
	return err
}

func (r *mod_staticfile) API_reback_version(ctx *Context) interface{} {
	info := &staticfileData{}
	fpt := formatStruct.ParseStructFields(info)
	db.QueryRow("SELECT "+fpt.ColsToString()+" from app_static_file where Id=?", ctx.Args.Get("Id")).Scan(fpt.GetPtrs()...)
	if info.Id == 0 {
		return errors.New("找不到对应的数据")
	}
	linkPath := ""
	if v, ok := staticallowpathmap[info.PathName]; ok {
		linkPath = v
	} else {
		return errors.New("该路径匹配有误")
	}
	os.Remove(linkPath)
	err := os.Symlink(filepath.Join(staticFile, info.FileData), linkPath)
	if err == nil {
		_, err = db.Exec("UPDATE app_static_file SET ModTime=?,ModId=? where Id=?", info.ModTime, info.ModId, info.Id)
	}
	return err
}
